use std::fmt;

use ntex::{
    http::StatusCode,
    web::{HttpResponse, WebResponseError},
};

#[derive(Debug, Clone)]
pub enum CustomError {
    NotFound(String),
    InternalServerError(String),
    AuthFailed(String),
    BadRequest(String),
}

// 实现 WebResponseError, 可返回http错误
impl WebResponseError for CustomError {
    //返回错误状态码
    fn status_code(&self) -> StatusCode {
        match self {
            CustomError::NotFound(_) => StatusCode::NOT_FOUND,
            CustomError::InternalServerError(_) => StatusCode::INTERNAL_SERVER_ERROR,
            CustomError::AuthFailed(_) => StatusCode::UNAUTHORIZED,
            CustomError::BadRequest(_) => StatusCode::BAD_REQUEST,
        }
    }

    //返回错误信息
    fn error_response(&self, _: &ntex::web::HttpRequest) -> HttpResponse {
        HttpResponse::new(self.status_code()).set_body(
            match self {
                CustomError::NotFound(msg) => msg,
                CustomError::InternalServerError(msg) => msg,
                CustomError::AuthFailed(msg) => msg,
                CustomError::BadRequest(msg) => msg,
            }
            .to_string()
            .into(),
        )
    }
}

//error_response 需要实现 fmt::Display
impl std::fmt::Display for CustomError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CustomError::NotFound(msg) => write!(f, "{msg}"),
            CustomError::InternalServerError(msg) => write!(f, "{msg}"),
            CustomError::AuthFailed(msg) => write!(f, "{msg}"),
            CustomError::BadRequest(msg) => write!(f, "{msg}"),
        }
    }
}

impl From<sqlx::Error> for CustomError {
    fn from(err: sqlx::Error) -> Self {
        match err {
            sqlx::Error::RowNotFound => CustomError::NotFound("row not found".into()),
            _ => CustomError::InternalServerError("internal server error, plaease contact the admin".into()),
        }
    }
}